/* libfake437 - a library for the rendering of code page 437 `graphics'
 * Copyright (C) 2008 Jack Kelly <endgame.dos@gmail.com>
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"
#include "fake437.h"
#include "defaults.h"

inline void f437_putChar(SDL_Surface *surface,
			 Uint16 offsetX, Uint16 offsetY,
			 Uint16 left, Uint16 top, Uint8 ch,
			 enum f437_color fg, enum f437_color bg){
  f437_putCharCustomColor(surface, offsetX, offsetY,
			  left, top, *f437_getChar(ch),
			  f437_getColor(fg), f437_getColor(bg));
}

inline void f437_putCharColor(SDL_Surface *surface,
			      Uint16 offsetX, Uint16 offsetY,
			      Uint16 left, Uint16 top, Uint8 ch,
			      const SDL_Color *fg, const SDL_Color *bg){
  f437_putCharCustomColor(surface, offsetX, offsetY,
			  left, top, *f437_getChar(ch), fg, bg);
}

inline void f437_putCharCustom(SDL_Surface *surface,
			       Uint16 offsetX, Uint16 offsetY,
			       Uint16 left, Uint16 top, const f437_char ch,
			       enum f437_color fg, enum f437_color bg){
  f437_putCharCustomColor(surface, offsetX, offsetY, left, top, ch,
			  f437_getColor(fg), f437_getColor(bg));
}

/* As seen in the SDL examples */
static void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel){
  int bpp = surface->format->BytesPerPixel;
  /* Here p is the address to the pixel we want to set */
  Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
  switch(bpp) {
  case 1:
    *p = pixel;
    break;
  case 2:
    *(Uint16 *)p = pixel;
    break;
  case 3:
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
      p[0] = (pixel >> 16) & 0xff;
      p[1] = (pixel >> 8) & 0xff;
      p[2] = pixel & 0xff;
#else
      p[0] = pixel & 0xff;
      p[1] = (pixel >> 8) & 0xff;
      p[2] = (pixel >> 16) & 0xff;
#endif
    break;
  case 4:
    *(Uint32 *)p = pixel;
    break;
  }
}

void f437_putCharCustomColor(SDL_Surface *surface,
			     Uint16 offsetX, Uint16 offsetY,
			     Uint16 left, Uint16 top, const f437_char ch,
			     const SDL_Color *fg, const SDL_Color *bg){
  Uint32 fgReal = SDL_MapRGB(surface->format, fg->r, fg->g, fg->b);
  Uint32 bgReal = SDL_MapRGB(surface->format, bg->r, bg->g, bg->b);
  int x;
  int y;
  if(SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
  for(y = 0 ; y < F437_CHAR_HEIGHT ; y++)
    for(x = 0 ; x < F437_CHAR_WIDTH ; x++){
      if(ch[y][x]) putpixel(surface,
			    offsetX + left * F437_CHAR_WIDTH  + x,
			    offsetY + top  * F437_CHAR_HEIGHT + y,
			    fgReal);
      else putpixel(surface,
		    offsetX + left * F437_CHAR_WIDTH  + x,
		    offsetY + top  * F437_CHAR_HEIGHT + y,
		    bgReal);
    }
  if(SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
}
